import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * mybatis-plus代码生成器
 *
 * @author zhangqing
 * @version 1.0
 * @date 2022/6/23
 */
public class CodeGenerator {

    //多个表名用逗号隔开
    static String tables = "user_info";
    static String projectCode = "practice";
    static String groupId = "personal.zq";
    static String modelName = "sys";
    static String author = "zhangqing";
    static String url = "jdbc:mysql://localhost:3306/practice?useUnicode=true&characterEncoding=UTF-8&useSSL=false";
    static String driverName = "com.mysql.jdbc.Driver";
    static String userName = "root";
    static String password = "root";
    //获取当前项目的文件位置
    static String projectPath = System.getProperty("user.dir") + "/";
    static String projectName = "my-practice-code";
    //模板路径，默认是/templates/
    static String templatesPath = "/injectiontemplates/";
    static Map<String, Object> map = new HashMap<>();


    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        mpg.setGlobalConfig(getGlobalConfig());
        // 数据源配置
        mpg.setDataSource(getDataSourceConfig());
        // 包配置
        mpg.setPackageInfo(getInjectionPackageConfig());
        // 自定义配置
        mpg.setCfg(getInjectionConfig());
        // 配置默认模板配置
        mpg.setTemplate(getTemplateConfig());
        // 策略配置
        mpg.setStrategy(getStrategy());
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }

    /**
     * 全局配置
     *
     * @return
     */
    static GlobalConfig getGlobalConfig() {
        GlobalConfig gc = new GlobalConfig();
        //自定义输出路径注释此处
        //gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor(author);
        //是否打开输出的目录，默认true
        gc.setOpen(false);
        //覆盖已有的文件，默认false(第一次生成时放开)
        gc.setFileOverride(true);
        gc.setBaseResultMap(true);
        gc.setBaseColumnList(true);
        // 设置日期类型为Date(若不设置时间类型都会变成LocalDateTime部分连接池例如druid是无法识别的)
        gc.setDateType(DateType.ONLY_DATE);
        return gc;
    }

    /**
     * 数据源
     *
     * @return
     */
    static DataSourceConfig getDataSourceConfig() {
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(url);
        dsc.setDriverName(driverName);
        dsc.setUsername(userName);
        dsc.setPassword(password);
        return dsc;
    }

    /**
     * 包配置
     *
     * @return
     */
    static InjectionPackageConfig getInjectionPackageConfig() {
        InjectionPackageConfig pc = new InjectionPackageConfig();
        // 自己修改模块名
        pc.setModuleName(modelName);
        pc.setParent(groupId);
        return pc;
    }

    /**
     * 自定义配置
     */
    static InjectionConfig getInjectionConfig() {
        List<FileOutConfig> fileOutConfigList = getFileOutConfigList();
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                map.put("time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                this.setMap(map);
            }
        };

        // 如果模板引擎是 freemarker
        cfg.setFileOutConfigList(fileOutConfigList);
        return cfg;
    }


    /**
     * 配置默认模板配置
     *
     * @return
     */
    static TemplateConfig getTemplateConfig() {
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setXml(null);
        templateConfig.setMapper(null);
        templateConfig.setService(null);
        templateConfig.setServiceImpl(null);
        templateConfig.setEntity(null);
        templateConfig.setController(null);
        return templateConfig;
    }

    /**
     * 策略配置
     *
     * @return
     */
    static StrategyConfig getStrategy() {
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        //是否为lombok模型，默认为false
        strategy.setEntityLombokModel(true);
        //前后端分离时可开启
        strategy.setRestControllerStyle(true);
        //数据库表，多表用逗号隔开
        //        strategy.setInclude(scanner("table name").split(","));
        strategy.setInclude(tables);
        //RequestMapping驼峰转连字符

        //        strategy.setControllerMappingHyphenStyle(true);
        //生成实体时生成生成数据库字段注解
        strategy.setEntityTableFieldAnnotationEnable(true);
        return strategy;
    }

    /**
     * 自定义输出配置
     *
     * @param templateFileName  模板文件名
     * @param childModuleSuffix 项目子模块后缀名
     * @param outPath           相对路径
     * @param fileSuffix        文件后缀
     * @param outputFileType    输出文件类型
     * @return FileOutConfig
     */
    static FileOutConfig getFileOutConfig(String templateFileName, String childModuleSuffix, String outPath,
                                          String fileSuffix, String outputFileType) {
        return new FileOutConfig(templatesPath + templateFileName) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String packagePath =
                        groupId.replace(".", "/") + "/" + projectCode + "/" + modelName + "/" + childModuleSuffix + outPath;
                map.put(fileSuffix, packagePath.replace("/", "."));
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return projectPath + projectName + "-" + childModuleSuffix + "/src/main/java/" + packagePath + "/" + tableInfo.getEntityName() + ("Entity".equals(fileSuffix) ? "" : fileSuffix) + outputFileType;
            }
        };
    }

    /**
     * 自定义输出配置列表，按配置顺序输出
     *
     * @return
     */
    static List<FileOutConfig> getFileOutConfigList() {
        List<FileOutConfig> focList = new ArrayList<>();
        //源码路径
        focList.add(getFileOutConfig("entity.java.ftl", "dao", "/entity", "Entity", StringPool.DOT_JAVA));

        focList.add(getFileOutConfig("mapper.java.ftl", "dao", "/mapper", "Mapper", StringPool.DOT_JAVA));
        focList.add(getFileOutConfig("mapper.xml.ftl", "dao", "/mapper/impl", "MapperImpl", StringPool.DOT_XML));

        focList.add(getFileOutConfig("dataService.java.ftl", "dao", "/dataservice", "DataService",
                StringPool.DOT_JAVA));
        focList.add(getFileOutConfig("dataServiceImpl.java.ftl", "dao", "/dataservice/impl", "DataServiceImpl",
                StringPool.DOT_JAVA));

        focList.add(getFileOutConfig("req.java.ftl", "client", "/req", "Req", StringPool.DOT_JAVA));
        focList.add(getFileOutConfig("resp.java.ftl", "client", "/resp", "Resp", StringPool.DOT_JAVA));

        focList.add(getFileOutConfig("service.java.ftl", "service", "", "Service", StringPool.DOT_JAVA));
        focList.add(getFileOutConfig("serviceImpl.java.ftl", "service", "/impl", "ServiceImpl", StringPool.DOT_JAVA));

        focList.add(getFileOutConfig("controller.java.ftl", "controller", "", "Controller", StringPool.DOT_JAVA));

        return focList;
    }
}
